package psn.kiko.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import psn.kiko.config.interceptor.HandlerRecordInterceptor;
import psn.kiko.config.properties.ResourceHandlerProperties;
import psn.kiko.config.properties.SwaggerApiDocProperties;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.io.File;
import java.util.List;

/**
 * 注册web层相关组件
 */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class WebMvcConfig extends WebMvcConfigurationSupport{
	private final SwaggerApiDocProperties swaggerApiDocProperties;
	private final ResourceHandlerProperties resourceHandlerProperties;
	@Value("${file.uploadDirString}")
	private String fileUploadDirString;//文件保存目录
	@Value("${file.mapping}")
	private String fileMapping;//文件请求地址与磁盘映射
	
	//swagger接口文档生成
	@Bean
	public Docket docket(){
		log.debug("{}接口文档: http://{}:{}/{}",
				swaggerApiDocProperties.getTitle(),
				swaggerApiDocProperties.getHost(),
				swaggerApiDocProperties.getPort(),
				swaggerApiDocProperties.getPathPattern());
		
		return new Docket(DocumentationType.SWAGGER_2)
				.apiInfo(getApiInfo())
				.groupName("管理端接口")
				.select()
				// 指定生成接口需要扫描的包
				.apis(RequestHandlerSelectors.basePackage(swaggerApiDocProperties.getBasePackage()))
				.paths(PathSelectors.any())
				.build();
	}
	
	private ApiInfo getApiInfo(){
		ApiInfo apiInfo = new ApiInfoBuilder()
				.title(swaggerApiDocProperties.getTitle())
				.version(swaggerApiDocProperties.getVersion())
				.description(swaggerApiDocProperties.getDescription())
				.build();
		return apiInfo;
	}
	
	//扩展消息转换器
	@Override
	protected void extendMessageConverters(List<HttpMessageConverter<?>> converters){
		log.debug("开始注册消息转换器...");
		//创建一个消息转换器
		MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
		//为消息转换器设置对象转换器，对象转换器可以将对象序列化为JSON
		converter.setObjectMapper(new JacksonObjectMapper());
		//将自己的转换器加入容器
		converters.add(0,converter);
	}
	
	/**
	 * 设置静态资源映射：请求url模式和资源位置的映射关系
	 */
	@Override
	protected void addResourceHandlers(ResourceHandlerRegistry registry){
		log.debug("开始添加资源处理配置...");
		//文件上传下载资源处理配置
		registry.addResourceHandler(fileMapping+"**")
				.addResourceLocations("file:"+fileUploadDirString+File.separator);
		//swagger接口文档资源处理配置
		for(ResourceHandlerProperties.ResourceHandlerLocationMapping mapping: resourceHandlerProperties.getResourceHandlerLocationMappings()){
			registry.addResourceHandler(mapping.getResourcePatterns())
					.addResourceLocations(mapping.getResourceLocations());
		}
	}
	
	private final HandlerRecordInterceptor handlerRecordInterceptor;
	@Override
	protected void addInterceptors(InterceptorRegistry registry){
		log.debug("注册处理器的拦截器");
		registry.addInterceptor(handlerRecordInterceptor);
	}
}
